package com.yueqian.framework.handler;


import java.util.stream.Collectors;

import javax.validation.ConstraintViolation;
import javax.validation.ConstraintViolationException;
import javax.validation.ValidationException;

import com.yueqian.framework.exception.GlobalException;
import com.yueqian.framework.exception.ValidatorException;
import org.springframework.context.support.DefaultMessageSourceResolvable;
import org.springframework.validation.BindException;
import org.springframework.web.bind.MethodArgumentNotValidException;
import org.springframework.web.bind.annotation.ControllerAdvice;
import org.springframework.web.bind.annotation.ExceptionHandler;
import org.springframework.web.bind.annotation.ResponseBody;

import com.yueqian.framework.entity.ResultEntity;

import lombok.extern.slf4j.Slf4j;

@ControllerAdvice
@ResponseBody
@Slf4j
public class GlobalExceptionHandler {

	@ExceptionHandler(ValidatorException.class)
	public ResultEntity<String> validatorException(ValidatorException exception) {
		return ResultEntity.error(exception.getCode(), exception.getMessage());
	}

	@ExceptionHandler(GlobalException.class)
	public ResultEntity<String> globalException(GlobalException exception) {
		return ResultEntity.error(exception.getExceptionEnum().getCode(), exception.getExceptionEnum().getMessage());
	}


	@ExceptionHandler(value = {BindException.class, ValidationException.class, MethodArgumentNotValidException.class})
	public ResultEntity<String> handleValidatedException(Exception e) {
		ResultEntity<String> resp = null;

		if (e instanceof MethodArgumentNotValidException) {
			// BeanValidation exception
			MethodArgumentNotValidException ex = (MethodArgumentNotValidException) e;
			resp = ResultEntity.error(10007,
					ex.getBindingResult().getAllErrors().stream()
							.map(DefaultMessageSourceResolvable::getDefaultMessage)
							.collect(Collectors.joining("; "))
			);
		} else if (e instanceof ConstraintViolationException) {
			// BeanValidation GET simple param
			ConstraintViolationException ex = (ConstraintViolationException) e;
			resp = ResultEntity.error(10007,
					ex.getConstraintViolations().stream()
							.map(ConstraintViolation::getMessage)
							.collect(Collectors.joining("; "))
			);
		} else if (e instanceof BindException) {
			// BeanValidation GET object param
			BindException ex = (BindException) e;
			resp = ResultEntity.error(10007,
					ex.getAllErrors().stream()
							.map(DefaultMessageSourceResolvable::getDefaultMessage)
							.collect(Collectors.joining("; "))
			);
		}
		return resp;
	}

}
